package 中等.树;

import java.util.Map;
import java.util.TreeMap;
import java.util.TreeSet;

/**
 * 实现一个 MyCalendar 类来存放你的日程安排。如果要添加的日程安排
 * 不会造成 重复预订 ，则可以存储这个新的日程安排。
 * 当两个日程安排有一些时间上的交叉时（例如两个日程安排都在同一时间
 * 内），就会产生 重复预订 。
 * 日程可以用一对整数 start 和 end 表示，这里的时间是半开区间，
 * 即 [start, end), 实数 x 的范围为，  start <= x < end 。
 * 实现 MyCalendar 类：
 * MyCalendar() 初始化日历对象。
 * boolean book(int start, int end) 如果可以将日程安排成功添加到日历中而不
 * 会导致重复预订，返回 true 。否则，返回 false 并且不要将该日程安排添加到日历中。
 * <p>
 * 来源：力扣（LeetCode）
 * 链接：https://leetcode.cn/problems/my-calendar-i
 */
public class 我的日程安排表I_729 {

    public static void main(String[] args) {

        MyCalendar myCalendar = new MyCalendar();
        myCalendar.book(10, 20);
        myCalendar.book(15, 25);

    }


}

class MyCalendar {

    private TreeSet<int[]> treeSet;

    public MyCalendar() {
        treeSet = new TreeSet<>((o1, o2) -> o1[0] - o2[0]);
        // 防止为空，先存放最小，最大值
        treeSet.add(new int[]{-1, -1});
        // 直接放 Integer.MAX_VALUE ,会有问题?
        treeSet.add(new int[]{1000000001, 1000000001});
    }

    public boolean book(int start, int end) {
        if (treeSet.size() == 2) {
            treeSet.add(new int[]{start, end});
            return true;
        }

        int[] curArr = {end, 0};
        // 找出树中大于 end 的最小元素
        int[] after = treeSet.ceiling(curArr);
        // 小于 end 的最大元素
        int[] before = treeSet.lower(curArr);
        if (start >= before[1] && end <= after[0]) {
            treeSet.add(new int[]{start, end});
            return true;
        }
        return false;
    }
}

class MyCalendar2 {

    private TreeMap<Integer, Integer> treeMap = new TreeMap<>();

    public MyCalendar2() {
        treeMap = new TreeMap<>((o1, o2) -> o1 - o2);
        // 防止为空，先存放最小，最大值
        treeMap.put(-1, -1);
        treeMap.put(1000000001, 1000000001);
    }

    public boolean book(int startTime, int endTime) {
        if (treeMap.size() == 2) {
            treeMap.put(startTime, endTime);
            return true;
        }

        Map.Entry<Integer, Integer> bigEntry = treeMap.ceilingEntry(endTime);
        Map.Entry<Integer, Integer> minEntry = treeMap.lowerEntry(endTime);
        if (minEntry.getValue() <= startTime && endTime <= bigEntry.getKey()) {
            treeMap.put(startTime, endTime);
            return true;
        }
        return false;
    }
}
// TODO 线段树